package com.lyf.scm.plan.domain.service.impl;


import com.github.pagehelper.PageInfo;
import com.lyf.scm.common.enums.OpContentEnum;
import com.lyf.scm.common.enums.OperationStatusEnum;
import com.lyf.scm.common.enums.ResponseMsg;
import com.lyf.scm.plan.api.dto.OperationLogRecordDTO;
import com.lyf.scm.plan.domain.repository.*;
import com.lyf.scm.plan.domain.service.OperationLogRecordService;
import com.lyf.scm.plan.domain.util.BigDataCacheUtil;
import com.lyf.scm.plan.insfrastructure.db.dataobject.OperationLogRecordDO;
import com.rome.arch.core.exception.RomeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

import static com.lyf.scm.plan.domain.util.BigDataCacheUtil.endTime;
import static com.lyf.scm.plan.domain.util.BigDataCacheUtil.startTime;


/**
 * @Author: huangtao
 * @Description: 操作日志
 * @Date: create in 2020/10/5
 */
@Slf4j
@Service
public class OperationLogRecordServiceImpl implements OperationLogRecordService {

    @Resource
    private OperationLogRecordRepository operationLogRecordRepository;

    @Resource
    private DirectlyExecuteRepository directlyExecuteRepository;

    @Resource
    private DirectlyStoreRepository directlyStoreRepository;

    @Resource
    private SalesPlanDirectlyAccuracyRepository salesPlanDirectlyAccuracyRepository;

    @Resource
    private SalePlanDirectlyDifferinRepository salePlanDirectlyDifferinRepository;

    @Resource
    private SalesPlanDirectlyRepository salesPlanDirectlyRepository;

    @Resource
    private DemandPlanRepository demandPlanRepository;

    @Resource
    private GmvTargetRepository gmvTargetRepository;

    @Resource
    private SalesPlanOtherRespository salesPlanOtherRespository;

    @Resource
    private SalesPlanOtherDifferinRespository salesPlanOtherDifferinRespository;

    @Resource
    private SalesPlanOtherAccuracyRespository salesPlanOtherAccuracyRespository;

    /**
     * 查询操作日志
     *
     * @param operationLogRecord
     * @return
     */
    @Override
    public PageInfo<OperationLogRecordDTO> getOperationLogs(OperationLogRecordDTO operationLogRecord) {
        return operationLogRecordRepository.getOperationLogs(operationLogRecord);
    }

    /**
     * 新增操作日志数据
     *
     * @param operationDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLogRecordDTO insertOperationLog(OperationLogRecordDTO operationDto) {
        return operationLogRecordRepository.insertOperationLog(operationDto);
    }

    /**
     * 编辑操作日志数据
     * @author wuyuanhang
     * @date 2020/11/16
     * @param operationDto 操作日志对象
     * @return int 更新条数
     */
    @Override
    public int updateOperationLog(OperationLogRecordDTO operationDto) {
        return operationLogRecordRepository.updateOperationLog(operationDto);
    }


    /**
     * 发起大数据定时任务，将状态调整为进行中(补救时间设定为，下一次定时人跑前三个小时时间点之前，本次大数据跑时间三个小时时间点之后)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bigDataInitiating() {
        //确定当前时间是否可发起大数据补救任务，1.根据拉取大数据时间点  获取该时间点处理的大数据为哪个时间的内容
        Date nowDate = new Date();
        BigDataCacheUtil.injectRemedyTimeCache(nowDate);
        if (startTime == null || endTime == null) {
            throw new RomeException(ResponseMsg.FAIL_5003.getCode(), ResponseMsg.FAIL_5003.getMsg());
        }
        //拉取可能需要补救的日志信息
        List<OperationLogRecordDO> operationLogRecordDOS = operationLogRecordRepository.pullReasonableLog(startTime, endTime, OpContentEnum.BIG_DATA_ERROR_DIRECT_LOG.getIndex());
        if (CollectionUtils.isEmpty(operationLogRecordDOS)) {
            throw new RomeException(ResponseMsg.FAIL_5001.getCode(), ResponseMsg.FAIL_5001.getMsg());
        }
        this.initiateRemedy(operationLogRecordDOS);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void opLogInitiating(List<Long> ids) {
//根据id改变其状态值
        if (CollectionUtils.isEmpty(ids)) {
            throw new RomeException(ResponseMsg.PARAM_ERROR.getCode(), ResponseMsg.PARAM_ERROR.getMsg());
        }
        int affectRow;
        for (int i = 0, length = ids.size(); i < length; i++) {
            affectRow = operationLogRecordRepository.updateStatusById(ids.get(i));
            if (affectRow <= 0) {
                throw new RomeException(ResponseMsg.FAIL.getCode(), ResponseMsg.FAIL.getMsg());
            }
        }
    }

    /**
     * 删除指定标识数据
     *
     * @param operationLogRecordDTOs
     * @return void
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rmByOpSign(List<OperationLogRecordDTO> operationLogRecordDTOs) {
        try {
            OperationLogRecordDTO operationLogRecordDTO;
            for (int i = 0, length = operationLogRecordDTOs.size(); i < length; i++) {
                operationLogRecordDTO = operationLogRecordDTOs.get(i);
                String opSign = operationLogRecordDTO.getOpSign();
                if (operationLogRecordDTO.getId() == null || StringUtils.isEmpty(opSign)) {
                    throw new RomeException(ResponseMsg.PARAM_ERROR.getCode(), ResponseMsg.PARAM_ERROR.getMsg());
                }
                //删除日志
                int affectRow = operationLogRecordRepository.deleteById(operationLogRecordDTO.getId());
                if (affectRow <= 0) {
                    throw new RomeException(ResponseMsg.FAIL.getCode(), ResponseMsg.FAIL.getMsg());
                }
                //删除表数据
                int opSource = operationLogRecordDTO.getOpSource();
                switch (opSource) {
                    case 1:
                        directlyExecuteRepository.deleteByOpSign(opSign);
                        break;
                    case 2:
                        directlyStoreRepository.deleteByOpSign(opSign);
                        break;
                    case 3:
                        salesPlanDirectlyAccuracyRepository.deleteByOpSign(opSign);
                        break;
                    case 4:
                        salePlanDirectlyDifferinRepository.deleteByOpSign(opSign);
                        break;
                    case 5:
                        salesPlanDirectlyRepository.deleteByOpSign(opSign);
                        break;
                    case 6:
                        demandPlanRepository.deleteByOpSign(opSign);
                        break;
                    case 7:
                        gmvTargetRepository.deleteByOpSign(opSign);
                        break;
                    case 8:
                        salesPlanOtherRespository.deleteByOpSign(opSign);
                        break;
                    case 9:
                        salesPlanOtherDifferinRespository.deleteByOpSign(opSign);
                        break;
                    case 10:
                        salesPlanOtherAccuracyRespository.deleteByOpSign(opSign);
                        break;
                    default:
                }
            }
        } catch (Exception e) {
            //回退状态值为成功，之前是处理中
            operationLogRecordRepository.batchUpdateOperationLogStatus(operationLogRecordDTOs);
            throw new RomeException(ResponseMsg.FAIL.getCode(), ResponseMsg.FAIL.getMsg());
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public void initiateRemedy(List<OperationLogRecordDO> operationLogRecordDOS) {
        //修改状态为发起中
        int affectRow;
        long count = operationLogRecordDOS.stream().filter(item -> OperationStatusEnum.PROCESSING.getType().equals(item.getOpStatus())).count();
        if (count > 0) {
            throw new RomeException(ResponseMsg.FAIL_5002.getCode(), ResponseMsg.FAIL_5002.getMsg());
        }
        for (OperationLogRecordDO item : operationLogRecordDOS) {
            item.setOpStatus(OperationStatusEnum.PROCESSING.getType());
            affectRow = operationLogRecordRepository.updateInitiatedStatus(item);
            if (affectRow <= 0) {
                throw new RomeException(ResponseMsg.FAIL_5002.getCode(), ResponseMsg.FAIL_5002.getMsg());
            }
        }
    }

    @Override
    public void updateToDel(String opSign){
        operationLogRecordRepository.updateToDel(opSign);
    }
}
